package com.softstone.sng.client;

import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.input.InputManager;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseAxisTrigger;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.Control;
import com.softstone.sng.messages.ManualControlMessage;
import java.io.IOException;

/**
 * When attached to a Spatial, searches for ManualControl and sends user input there, only used on client for current
 * user entity.
 *
 * @author normenhansen
 */
public class UserInputControl implements Control, ActionListener, AnalogListener
{
  //TODO: add support for joysticks, mouse axis etc. and localization

  private InputManager inputManager;
  private boolean enabled = true;
  private float moveX = 0;
  private float moveY = 0;
  private float moveZ = 0;
  private float steerX = 0;
  private float steerY = 0;

  public UserInputControl(InputManager inputManager)
  {
    this.inputManager = inputManager;
    prepareInputManager();
  }

  private void prepareInputManager()
  {
    inputManager.addMapping("UserInput_Left_Key", new KeyTrigger(KeyInput.KEY_A));
    inputManager.addMapping("UserInput_Right_Key", new KeyTrigger(KeyInput.KEY_D));
    inputManager.addMapping("UserInput_Up_Key", new KeyTrigger(KeyInput.KEY_Q));
    inputManager.addMapping("UserInput_Down_Key", new KeyTrigger(KeyInput.KEY_Z));
    inputManager.addMapping("UserInput_Front_Key", new KeyTrigger(KeyInput.KEY_W));
    inputManager.addMapping("UserInput_Back_Key", new KeyTrigger(KeyInput.KEY_S));
    inputManager.addMapping("UserInput_Left_Arrow_Key", new KeyTrigger(KeyInput.KEY_LEFT));
    inputManager.addMapping("UserInput_Right_Arrow_Key", new KeyTrigger(KeyInput.KEY_RIGHT));
    inputManager.addMapping("UserInput_Mouse_Axis_X_Left", new MouseAxisTrigger(MouseInput.AXIS_X, true));
    inputManager.addMapping("UserInput_Mouse_Axis_X_Right", new MouseAxisTrigger(MouseInput.AXIS_X, false));
    inputManager.addMapping("UserInput_Mouse_Axis_Y_Up", new MouseAxisTrigger(MouseInput.AXIS_Y, true));
    inputManager.addMapping("UserInput_Mouse_Axis_Y_Down", new MouseAxisTrigger(MouseInput.AXIS_Y, false));
    inputManager.addListener(this,
            "UserInput_Left_Key",
            "UserInput_Right_Key",
            "UserInput_Up_Key",
            "UserInput_Down_Key",
            "UserInput_Front_Key",
            "UserInput_Back_Key",
            "UserInput_Left_Arrow_Key",
            "UserInput_Right_Arrow_Key",
            "UserInput_Mouse_Axis_X_Left",
            "UserInput_Mouse_Axis_X_Right",
            "UserInput_Mouse_Axis_Y_Up",
            "UserInput_Mouse_Axis_Y_Down");
  }

  public void setEnabled(boolean enabled)
  {
    this.enabled = enabled;
  }

  public boolean isEnabled()
  {
    return enabled;
  }

  public void render(RenderManager rm, ViewPort vp)
  {
  }

  public void onAnalog(String binding, float value, float tpf)
  {
    if (!isEnabled())
    {
      return;
    }
    if (binding.equals("UserInput_Mouse_Axis_X_Left"))
    {
      steerX += value;
    }
    else if (binding.equals("UserInput_Mouse_Axis_X_Right"))
    {
      steerX -= value;
    }
    else if (binding.equals("UserInput_Mouse_Axis_Y_Up"))
    {
      steerY += value;
    }
    else if (binding.equals("UserInput_Mouse_Axis_Y_Down"))
    {
      steerY -= value;
    }
  }

  public void onAction(String binding, boolean value, float tpf)
  {
    if (!isEnabled())
    {
      return;
    }
    if (binding.equals("UserInput_Left_Key"))
    {
      if (!value)
      {
        moveX += 1;
      }
      else
      {
        moveX -= 1;
      }
//      messageQueue.add(new ManualControlMessage(0, steerX, steerY, moveX, moveY, moveZ));
      steerX = 0; steerY = 0;
    }
    else if (binding.equals("UserInput_Right_Key"))
    {
      if (!value)
      {
        moveX -= 1;
      }
      else
      {
        moveX += 1;
      }
//      messageQueue.add(new ManualControlMessage(0, steerX, steerY, moveX, moveY, moveZ));
      steerX = 0; steerY = 0;
    }
    else if (binding.equals("UserInput_Up_Key"))
    {
      if (!value)
      {
        moveY += 1;
      }
      else
      {
        moveY -= 1;
      }
//      messageQueue.add(new ManualControlMessage(0, steerX, steerY, moveX, moveY, moveZ));
      steerX = 0; steerY = 0;
    }
    else if (binding.equals("UserInput_Down_Key"))
    {
      if (!value)
      {
        moveY -= 1;
      }
      else
      {
        moveY += 1;
      }
//      messageQueue.add(new ManualControlMessage(0, steerX, steerY, moveX, moveY, moveZ));
      steerX = 0; steerY = 0;
    }
    else if (binding.equals("UserInput_Front_Key"))
    {
      if (!value)
      {
        moveZ += 1;
      }
      else
      {
        moveZ -= 1;
      }
//      messageQueue.add(new ManualControlMessage(0, steerX, steerY, moveX, moveY, moveZ));
      steerX = 0; steerY = 0;
    }
    else if (binding.equals("UserInput_Back_Key"))
    {
      if (!value)
      {
        moveZ -= 1;
      }
      else
      {
        moveZ += 1;
      }
//      messageQueue.add(new ManualControlMessage(0, steerX, steerY, moveX, moveY, moveZ));
      steerX = 0; steerY = 0;
    }
  }

  public Control cloneForSpatial(Spatial spatial)
  {
    throw new UnsupportedOperationException("Not supported.");
  }

  public void write(JmeExporter ex) throws IOException
  {
    throw new UnsupportedOperationException("Not supported.");
  }

  public void read(JmeImporter im) throws IOException
  {
    throw new UnsupportedOperationException("Not supported.");
  }

  public void setSpatial(Spatial spatial)
  {
  }

  public void update(float tpf)
  {
    if (steerX != 0 || steerY != 0)
    {
//      messageQueue.add(new ManualControlMessage(0, steerX, steerY, moveX, moveY, moveZ));
      steerX = 0;
      steerY = 0;
    }
  }
}
